import { Request, Response, NextFunction } from 'express';
import { AppError, ApiResponse } from '../types/agent';
import { isDevelopment } from '../config';

/**
 * 全局错误处理中间件
 */
export function errorHandler(
  error: AppError | Error,
  req: Request,
  res: Response,
  next: NextFunction
): void {
  // 如果响应已经发送，则交给默认的Express错误处理器
  if (res.headersSent) {
    return next(error);
  }

  // 默认错误状态码
  let statusCode = 500;
  let message = 'Internal Server Error';
  let code = 'INTERNAL_ERROR';

  // 处理自定义应用错误
  if (error instanceof Error && 'statusCode' in error) {
    const appError = error as AppError;
    statusCode = appError.statusCode || 500;
    message = appError.message;
    code = appError.code || 'APP_ERROR';
  }
  // 处理常见的HTTP错误
  else if (error.name === 'ValidationError') {
    statusCode = 400;
    message = 'Validation Error';
    code = 'VALIDATION_ERROR';
  }
  else if (error.name === 'CastError') {
    statusCode = 400;
    message = 'Invalid ID format';
    code = 'INVALID_ID';
  }
  else if (error.name === 'SyntaxError' && 'body' in error) {
    statusCode = 400;
    message = 'Invalid JSON format';
    code = 'INVALID_JSON';
  }
  else if (error.message) {
    message = error.message;
  }

  // 记录错误日志
  console.error(`[${new Date().toISOString()}] Error ${statusCode}:`, {
    message: error.message,
    stack: error.stack,
    url: req.url,
    method: req.method,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  // 构建错误响应
  const errorResponse: ApiResponse = {
    success: false,
    error: message,
    ...(isDevelopment() && {
      details: {
        code,
        stack: error.stack,
        timestamp: new Date().toISOString()
      }
    })
  };

  res.status(statusCode).json(errorResponse);
}

/**
 * 404 Not Found 处理中间件
 */
export function notFoundHandler(req: Request, res: Response): void {
  const response: ApiResponse = {
    success: false,
    error: `Route ${req.method} ${req.path} not found`
  };
  
  res.status(404).json(response);
}

/**
 * 异步路由错误捕获包装器
 */
export function asyncHandler(
  fn: (req: Request, res: Response, next: NextFunction) => Promise<any>
) {
  return (req: Request, res: Response, next: NextFunction) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
}

/**
 * 请求验证中间件
 */
export function validateRequest(
  requiredFields: string[],
  location: 'body' | 'params' | 'query' = 'body'
) {
  return (req: Request, res: Response, next: NextFunction): void => {
    const data = req[location];
    const missingFields: string[] = [];
    
    for (const field of requiredFields) {
      if (!data[field]) {
        missingFields.push(field);
      }
    }
    
    if (missingFields.length > 0) {
      const response: ApiResponse = {
        success: false,
        error: `Missing required fields: ${missingFields.join(', ')}`
      };
      res.status(400).json(response);
      return;
    }
    
    next();
  };
}

/**
 * 请求日志中间件
 */
export function requestLogger(req: Request, res: Response, next: NextFunction): void {
  const start = Date.now();
  
  // 记录请求开始
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.path} - Start`);
  
  // 监听响应结束
  res.on('finish', () => {
    const duration = Date.now() - start;
    console.log(
      `[${new Date().toISOString()}] ${req.method} ${req.path} - ${res.statusCode} (${duration}ms)`
    );
  });
  
  next();
}

/**
 * CORS 预检请求处理
 */
export function corsHandler(req: Request, res: Response, next: NextFunction): void {
  // 处理预检请求
  if (req.method === 'OPTIONS') {
    res.header('Access-Control-Allow-Origin', req.headers.origin || '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    res.header('Access-Control-Allow-Credentials', 'true');
    res.sendStatus(200);
    return;
  }
  
  next();
}

/**
 * 速率限制中间件（简单实现）
 */
const requestCounts = new Map<string, { count: number; resetTime: number }>();

export function rateLimit(
  maxRequests: number = 100,
  windowMs: number = 15 * 60 * 1000 // 15分钟
) {
  return (req: Request, res: Response, next: NextFunction): void => {
    const clientId = req.ip || 'unknown';
    const now = Date.now();
    
    // 获取或创建客户端记录
    let clientData = requestCounts.get(clientId);
    
    if (!clientData || now > clientData.resetTime) {
      // 重置或创建新的计数
      clientData = {
        count: 1,
        resetTime: now + windowMs
      };
      requestCounts.set(clientId, clientData);
    } else {
      clientData.count++;
    }
    
    // 检查是否超过限制
    if (clientData.count > maxRequests) {
      const response: ApiResponse = {
        success: false,
        error: 'Too many requests, please try again later'
      };
      res.status(429).json(response);
      return;
    }
    
    // 添加速率限制头
    res.header('X-RateLimit-Limit', maxRequests.toString());
    res.header('X-RateLimit-Remaining', (maxRequests - clientData.count).toString());
    res.header('X-RateLimit-Reset', new Date(clientData.resetTime).toISOString());
    
    next();
  };
}

/**
 * 清理过期的速率限制记录
 */
setInterval(() => {
  const now = Date.now();
  for (const [clientId, data] of requestCounts.entries()) {
    if (now > data.resetTime) {
      requestCounts.delete(clientId);
    }
  }
}, 5 * 60 * 1000); // 每5分钟清理一次